package org.example.baseinfo.util;

import lombok.extern.slf4j.Slf4j;

import java.sql.Time;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;


@Slf4j
public final class DateUtils {

    public static final String FULL_FORMAT = "yyyy-MM-dd HH:mm:ss";

    private static final String FORMAT = "yyyyMMddHHmmss";

    private static final String SIMPLE_NOSPE_FORMAT = "yyyyMMdd";

    private static final String SIMPLE_FORMAT = "yyyy-MM-dd";

    private static final String SIMPLE_TIME_FORMAT = "HH:mm:ss";

    private static final String ERROR_NAME = "时间处理异常";

    private DateUtils() {
    }

    /**
     * 获得当前 时:分:秒
     *
     * @return .
     */
    public static String getCurrentTime() {
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat(SIMPLE_TIME_FORMAT);
        return df.format(calendar.getTime());
    }

    /**
     * 得到几天前的时间
     *
     * @param d   .
     * @param day .
     * @return .
     */
    public static Date getDateBefore(Date d, int day) {
        Calendar now = Calendar.getInstance();
        now.setTime(d);
        now.set(Calendar.DATE, now.get(Calendar.DATE) - day);
        return now.getTime();
    }

    /**
     * 得到几天后的时间
     *
     * @param d   .
     * @param day .
     * @return .
     */
    public static Date getDateAfter(Date d, int day) {
        Calendar now = Calendar.getInstance();
        now.setTime(d);
        now.set(Calendar.DATE, now.get(Calendar.DATE) + day);
        return now.getTime();
    }

    /**
     * 得到 (Date类型的日期+N个月) 的日期Date类型  加法
     *
     * @param date  .
     * @param month .
     * @return .
     */
    public static Date getAddMonth(Date date, int month) {
        Calendar now = Calendar.getInstance();
        now.setTime(date);
        now.add(Calendar.MONTH, month);
        return now.getTime();
    }

    /**
     * 得到 (Date类型的日期-N个月) 的日期字符串   减法
     *
     * @param date  .
     * @param month .
     * @return .
     */
    public static Date getSubtractMonth(Date date, int month) {
        Calendar now = Calendar.getInstance();
        now.setTime(date);
        now.add(Calendar.MONTH, -month);
        return now.getTime();
    }

    /**
     * 得到 (Date类型的日期+N年) 的日期Date类型  加法
     *
     * @param date .
     * @param year .
     * @return .
     */
    public static Date getAddYear(Date date, int year) {
        Calendar now = Calendar.getInstance();
        now.setTime(date);
        now.add(Calendar.YEAR, year);
        return now.getTime();
    }

    /**
     * 得到 (Date类型的日期-N个月) 的日期字符串   减法
     *
     * @param date .
     * @param year .
     * @return .
     */
    public static Date getSubtractYear(Date date, int year) {
        Calendar now = Calendar.getInstance();
        now.setTime(date);
        now.add(Calendar.YEAR, -year);
        return now.getTime();
    }

    private static Calendar initCurrentDate() {
        Date date = new Date(System.currentTimeMillis());
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c;
    }

    public static int getCurrentYear() {
        Calendar c = initCurrentDate();
        return c.get(Calendar.YEAR);
    }

    public static int getCurrentMonth() {
        return initCurrentDate().get(Calendar.MONTH) + 1;
    }

    public static int getCurrentDay() {
        return initCurrentDate().get(Calendar.DAY_OF_MONTH);
    }

    public static int getCurrentHour() {
        return initCurrentDate().get(Calendar.HOUR_OF_DAY);
    }

    public static int getCurrentMinute() {
        return initCurrentDate().get(Calendar.MINUTE);
    }

    public static int getCurrentSecond() {
        return initCurrentDate().get(Calendar.SECOND);
    }

    public static String getCurrentDate(String format) {
        SimpleDateFormat parse = new SimpleDateFormat(format);
        return parse.format(new Date());
    }

    public static Date parseDate(String str, String parsePatterns) throws ParseException {
        if (str == null || parsePatterns == null) {
            throw new IllegalArgumentException("Date and Patterns must not be null");
        }

        SimpleDateFormat parser;
        ParsePosition pos = new ParsePosition(0);
        parser = new SimpleDateFormat(parsePatterns);
        pos.setIndex(0);
        Date date = parser.parse(str, pos);
        if (date != null && pos.getIndex() == str.length()) {
            return date;
        }
        throw new ParseException("Unable to parse the date: " + str, -1);
    }

    public static String dateToString(Date date, String par) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(par);
        return sdf.format(date);
    }

    /**
     * 将日期字符串转换为长整型
     *
     * @param date 格式(yyyy-MM-dd)
     * @return .
     */
    public static long strToDateLong(String date) {
        long l = 0L;
        try {
            Calendar ca = Calendar.getInstance();
            ca.setTime(java.sql.Date.valueOf(date));
            l = ca.getTimeInMillis();
        } catch (Exception e) {
            log.error("日期字符串转长整形错误", e);
        }
        return l;
    }

    public static String longToStrDate(String format, long time) {
        DateFormat df = new SimpleDateFormat(format);
        return df.format(new Date(time));
    }

    public static Date strToDate(String str, String parsePatterns) throws ParseException {
        return parseDate(str, parsePatterns);
    }

    /**
     * 得到 n 天后的日期
     *
     * @param days .
     * @return .
     */
    public static Date getAfterCurrentDay(int days) {
        Date result = null;
        Calendar calendar = Calendar.getInstance();
        try {
            calendar.add(Calendar.DAY_OF_WEEK, +days);
            result = calendar.getTime();
        } catch (Exception e) {
            log.error(ERROR_NAME, e);
        }
        return result;
    }

    /**
     * 得到当前日期的年月日时分秒
     *
     * @return .
     */
    public static String getCurrentDateTimeString() {
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat(FORMAT);
        return df.format(calendar.getTime());
    }

    /**
     * 得到当前日期的年-月-日 时:分:秒
     *
     * @return .
     */
    public static String getCurrentDateToString() {
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat(FULL_FORMAT);
        return df.format(calendar.getTime());
    }

    /**
     * 得到当前日期的年-月-日
     *
     * @return .
     */
    public static String getCurrentDateSimpleToString() {
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat(SIMPLE_FORMAT);
        return df.format(calendar.getTime());
    }

    /**
     * 得到当前日期的yyyymmdd
     *
     * @return .
     */
    public static String getCurrentDateSimpleNoSpeToString() {
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat(SIMPLE_NOSPE_FORMAT);
        return df.format(calendar.getTime());
    }

    /**
     * 得到当前日期的年-月-日
     *
     * @return .
     */
    public static Date getCurrentDate() {
        Calendar calendar = Calendar.getInstance();
        return calendar.getTime();
    }

    /**
     * 得到当前日期的年-月-日
     *
     * @return .
     */
    public static Timestamp getCurrentDateTimestamp() {
        Calendar calendar = Calendar.getInstance();
        return new Timestamp(calendar.getTime().getTime());
    }

    /**
     * 得到当天到下周的日期
     *
     * @return .
     */
    public static String getNextWeekToString() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_WEEK, +6);
        SimpleDateFormat df = new SimpleDateFormat(SIMPLE_FORMAT);
        return df.format(calendar.getTime());
    }

    /**
     * 得到明天的时间
     *
     * @return .
     */
    public static String getNextDayToString(String day) {
        String result = "";
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat(SIMPLE_FORMAT);
        try {
            calendar.setTime(df.parse(day));
            calendar.add(Calendar.DAY_OF_WEEK, +1);
            result = df.format(calendar.getTime());
        } catch (ParseException e) {
            log.error(ERROR_NAME, e);
        }
        return result;
    }

    public static String getLastWeekToString() {
        String result = "";
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat(SIMPLE_FORMAT);
        try {
            // 周数减一，即上周
            calendar.add(Calendar.WEEK_OF_MONTH, -1);
            result = df.format(calendar.getTime());
        } catch (Exception e) {
            log.error(ERROR_NAME, e);
        }
        return result;
    }

    /**
     * 获取昨天日期
     *
     * @param day .
     * @return .
     */
    public static String getYestarDayToString(String day) {
        String result = "";
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat(SIMPLE_FORMAT);
        try {
            calendar.setTime(df.parse(day));
            calendar.add(Calendar.DAY_OF_WEEK, -1);
            result = df.format(calendar.getTime());
        } catch (ParseException e) {
            log.error(ERROR_NAME, e);
        }
        return result;
    }

    /**
     * 字符串日期转Date类型
     *
     * @param str .
     * @return .
     */
    public static Date stringToSimpleDate(String str) {
        if (str == null || "".equals(str)) {
            return null;
        }
        SimpleDateFormat df = new SimpleDateFormat(SIMPLE_FORMAT);
        try {
            return df.parse(str);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 字符串日期转Date类型
     *
     * @param str .
     * @return .
     */
    public static Date stringToFullDate(String str) {
        if (str == null || "".equals(str)) {
            return null;
        }
        SimpleDateFormat df = new SimpleDateFormat(FULL_FORMAT);
        try {
            return df.parse(str);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * Date类型转字符串日期
     *
     * @param date .
     * @return .
     */
    public static String dateToSimpleString(Date date) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat df = new SimpleDateFormat(SIMPLE_FORMAT);
        return df.format(date);
    }

    /**
     * Date类型转字符串日期
     *
     * @param date .
     * @return .
     */
    public static String dateToFullString(Date date) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat df = new SimpleDateFormat(FULL_FORMAT);
        return df.format(date);
    }

    /**
     * 根据日期得到星期几
     *
     * @param date .
     * @return .
     */
    public static String getWeekChinese(String date) {
        String[] weekDays = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat(SIMPLE_FORMAT);
        try {
            cal.setTime(df.parse(date));
        } catch (ParseException e) {
            log.error(ERROR_NAME, e);
        }
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0) {
            w = 0;
        }
        return weekDays[w];
    }

    /**
     * 判断两个时间的大小 是否后面那个大于前面那个 格式 yyyy-MM-dd
     *
     * @param startStr .
     * @param endStr   .
     * @return true为是 false为否
     */
    public static boolean judgeDate(String startStr, String endStr) {
        Date startDate = stringToSimpleDate(startStr);
        Date endDate = stringToSimpleDate(endStr);
        if (startDate == null) {
            return false;
        }
        return startDate.before(endDate);
    }

    /**
     * 判断两个时间的大小 是否后面那个大于或等于前面那个 格式 yyyy-MM-dd
     *
     * @param startStr .
     * @param endStr   .
     * @return true为是 false为否
     */
    public static boolean judgeDateEqual(String startStr, String endStr) {
        Date startDate = stringToSimpleDate(startStr);
        Date endDate = stringToSimpleDate(endStr);
        if (startDate == null) {
            return false;
        }
        return startDate.before(endDate) || startDate.compareTo(endDate) == 0;
    }

    /**
     * 得到多少天的日期 正数为加 负数为减
     *
     * @param str .
     * @param day .
     * @return .
     */
    public static String getNumAfterDate(String str, int day) {
        Date startDate = stringToSimpleDate(str);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        calendar.add(Calendar.DAY_OF_WEEK, day);
        return dateToSimpleString(calendar.getTime());
    }

    /**
     * 将UNIXTIME转为普通的时间
     *
     * @param unixTime .
     * @return .
     */
    public static String unixTimeToString(String unixTime) {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(Long.parseLong(unixTime));
        return dateToSimpleString(c.getTime());
    }

    /**
     * 将普通的日间转为UNIXTIME
     *
     * @param date .
     * @return .
     */
    public static String stringToUnixTime(String date) {
        Calendar c = Calendar.getInstance();
        Date date2 = stringToSimpleDate(date);
        c.setTime(date2);
        return c.getTimeInMillis() + "";

    }

    /**
     * 将时间字符串转化成Timestamp时间戳（String的类型必须形如： yyyy-mm-dd hh:mm:ss 这样的格式，否则报错）
     *
     * @param tsStr .
     * @return Timestamp
     */
    public static Timestamp stringToTimestamp(String tsStr) {
        Timestamp ts = new Timestamp(System.currentTimeMillis());
        try {
            ts = Timestamp.valueOf(tsStr);
        } catch (Exception e) {
            log.error(ERROR_NAME, e);
        }
        return ts;
    }

    /**
     * 时间戳转字符串
     *
     * @param ccTime .
     * @return .
     */
    public static String getStrByTimestamp(Timestamp ccTime) {
        SimpleDateFormat sdf = new SimpleDateFormat(FULL_FORMAT);
        return sdf.format(ccTime);
    }

    public static Time strToTime(String strDate) {
        if ("".equals(strDate) || strDate == null) {
            return null;
        }
        return Time.valueOf(strDate);
    }

    public static Time getTime() {
        Date d = new Date();
        return new Time(d.getTime());
    }

    /**
     * dateB - dateA  的日期天数
     *
     * @param dateA .
     * @param dateB .
     * @return .
     */
    public static int getBetweenDayNumber(Date dateA, Date dateB) {
        long dayNumber = 0;
        long day = 24L * 60L * 60L * 1000L;
        try {
            dayNumber = (dateB.getTime() - dateA.getTime()) / day;
        } catch (Exception e) {
            log.error(ERROR_NAME, e);
        }
        return (int) dayNumber;
    }

    /**
     * 计算两个日期相差的天数 date2-date1
     *
     * @param date1 .
     * @param date2 .
     * @return .
     */
    public static int daysBetween(Date date1, Date date2) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date1);
        long time1 = cal.getTimeInMillis();
        cal.setTime(date2);
        long time2 = cal.getTimeInMillis();
        long betweenDays = (time2 - time1) / (1000 * 3600 * 24);
        return Integer.parseInt(String.valueOf(betweenDays));
    }

    /**
     * 计算两个日期相差的秒数 date2-date1
     *
     * @param date1 .
     * @param date2 .
     * @return .
     */
    public static int secondsBetween(Date date1, Date date2) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date1);
        long time1 = cal.getTimeInMillis();
        cal.setTime(date2);
        long time2 = cal.getTimeInMillis();
        long betweenDays = (time2 - time1) / 1000;
        return Integer.parseInt(String.valueOf(betweenDays));
    }

    /**
     * 日期增加天数
     *
     * @param date    .
     * @param addDays .
     * @return .
     */
    public static Date dateAddDays(Date date, int addDays) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, addDays);
        return calendar.getTime();
    }

    /**
     * 日期增加小时
     *
     * @param date     .
     * @param addHours .
     * @return .
     */
    public static Date dateAddHours(Date date, int addHours) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.HOUR_OF_DAY, addHours);
        return calendar.getTime();
    }

    /**
     * 日期增加分钟
     *
     * @param date       .
     * @param addMinutes .
     * @return .
     */
    public static Date dateAddMinutes(Date date, int addMinutes) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, addMinutes);
        return calendar.getTime();
    }

    /**
     * long类型转换为String类型
     *
     * @param currentTime 要转换的long类型的时间
     * @param formatType  要转换的string类型的时间格式
     * @return .
     * @throws ParseException .
     */
    public static String longToString(long currentTime, String formatType) throws ParseException {
        // long类型转成Date类型
        Date date = longToDate(currentTime, formatType);
        // date类型转成String
        return dateToString(date, formatType);
    }

    /**
     * string类型转换为date类型
     *
     * @param strTime    要转换的string类型的时间，formatType要转换的格式yyyy-MM-dd HH:mm:ss//yyyy年MM月dd日
     * @param formatType .
     * @return .
     * @throws ParseException .
     */
    public static Date stringToDate(String strTime, String formatType) throws ParseException {
        SimpleDateFormat formatter = new SimpleDateFormat(formatType);
        return formatter.parse(strTime);
    }

    /**
     * long转换为Date类型
     *
     * @param currentTime 要转换的long类型的时间
     * @param formatType  要转换的时间格式yyyy-MM-dd HH:mm:ss//yyyy年MM月dd日 HH时mm分ss秒
     * @return .
     * @throws ParseException .
     */
    public static Date longToDate(long currentTime, String formatType) throws ParseException {
        // 根据long类型的毫秒数生命一个date类型的时间
        Date dateOld = new Date(currentTime);
        // 把date类型的时间转换为string
        String sDateTime = dateToString(dateOld, formatType);
        return stringToDate(sDateTime, formatType);
    }

    /**
     * date类型转换为long类型
     *
     * @param date 要转换的date类型的时间
     * @return .
     */
    public static long dateToLong(Date date) {
        return date.getTime();
    }

    /**
     * 时 分 秒 置0
     *
     * @param d      .
     * @param hour   .
     * @param min    .
     * @param second .
     * @return .
     */
    public static Date setPrecise(Date d, int hour, int min, int second) {
        GregorianCalendar calendar = new GregorianCalendar();
        calendar.setTime(d);
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, min);
        calendar.set(Calendar.SECOND, second);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取当前时间第二天的起始时间
     *
     * @return .
     * @author ZhangWei
     */
    public static Date getNextDayStartTime() {
        Date date = new Date();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_YEAR, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }
}
